package scala.test_empty

/**
 * @author 黄海峰 2021/4/15 15:37
 * */
object EmptyType {
  def main(args: Array[String]): Unit = {
    /**
     * Null、null、Nil、Nothing、None、Unit
     *
     * Nothing is a subtype of all types, also called the bottom type.
     * There is no value that has type Nothing.
     * A common use is to signal non-termination such as a thrown exception, program exit, or an infinite loop
     * (i.e., it is the type of an expression which does not evaluate to a value,
     * or a method that does not return normally).
     *
     * Null is a subtype of all reference types
     * (i.e. any subtype of AnyRef).
     * It has a single value identified by the keyword literal null.
     * Null is provided mostly for interoperability with other JVM languages
     * and should almost never be used in Scala code. We’ll cover alternatives to null later in the tour.
     *
     * The null reference is used to represent an absent value
     * as it’s probably the most familiar one for most of us because of the dreaded NullPointerException it causes.
     *
     * Nil is an empty singleton object list that extends the List type,
     * therefore, it has all fields and methods that any other List object has,
     * and it’s usually used to initialize empty lists
     *
     * None is a subtype of Option type.
     * We’ve seen the problems caused when functions return null values
     * in case they don’t have any values to return.
     * This may cause calling programs to crash if it doesn't properly handle null.
     *
     * Unit is the return type of functions returning nothing.
     * It’s equivalent to the void type in Java except for one difference:
     * The Unit type in Scala has one singleton value that is (), but void in Java does not have any value
     *
     *
     */

    val nullRefCar: Car = null
    try {
      println(nullRefCar.mark)
    } catch {
      case npe: NullPointerException => {
        println("【外】异常：%s".format(npe))
        try {
//          throw new IllegalArgumentException
          logException(npe)
        } catch {
          case npe: MyException => println("【内】我的异常：%s".format(npe))
          case npe: Exception with MyException => println("【内】我的异常：%s".format(npe))
          case npe: NullPointerException => println("【内】NPE异常：%s".format(npe))
          case _ => println("【内】其他异常：%s".format(npe))
        }
      }
      case npe: Exception => println("【外】其他异常：%s".format(npe))
    }

    val nullMakeCar: Car = Car(null)
    println(nullMakeCar.mark)

    val userList = Nil
    println(userList.length)

    val patientList: List[String] = Nil
    println(patientList.length)
    println(patientList.isEmpty)

    val studentRegister: Map[Int, String] = Map(1 -> "dean", 2 -> "jone")
    printStudent(getStudentName(studentRegister, 3))

    /**
     * nullObj 推断出的类型是 Null。 由于该类型的唯一值是 null，因此无法分配其他的值。
     */
    var nullObj = null
//    nullObj = new Car("sss")
  }

  def getStudentName(studentRegister: Map[Int, String], roll: Int): Option[String] = {
    studentRegister.get(roll)
  }

  def printStudent(student: Option[String]): Unit = {
    student match {
      case Some(str) => println("Student Name is: %s".format(str))
      case None => println("No Student!")
    }
  }

  def logException(e: Exception): Nothing = {
    println("logging Exception: %s".format(e))
    throw new MyException("My New Exception")
  }

}
